#include <stdio.h>
#include <utils/logger.h>
#include "baseinfo/baseinfo.h"

//#include "acquisition/acquisition.h"
#include "transport/transport_manager.h"
#include "acquisition/acquisition.h"
#include "remoteservice/remoteservice.h"
#include <acqmodbus/acqmodbus.h>
#include "utils/signals.h"
#include "transport/transport.h"
#include <defines.h>
#include <utils/logger.h>
#include <mcheck.h>

#include <unistd.h>
#include <fcntl.h>
#include <sstream>
#include <utils/config.h>

#ifdef RUN_TEST
#include <test/htcomhex.h>
#endif

void setVersion();
void sigint_catch(int sig);
void sig_handler(int sig);
void dotask(int flag);

int main(int argc, char *argv[])
{
    /*
     * 获取配置信息
     */
    int ch;

    while ((ch = getopt(argc,argv,"ivsh"))) {
        switch(ch)
        {
        case 'h':
            printf("-v  获取版本号\n");
            printf("-s  绑定版本号\n");
            printf("-i  系统类型\n");
            return 0;
        case 'v':
            printf(DAS_VERSION);
            return 0;
        case 's':
            setVersion();
            return 0;
        case 'i':
            printf(SYSVER);
            return 0;
        default:
            setVersion();
            break;
        }
        break;
    }

    /*
     * 初始化通讯
     */
    InitMsg();
    SetMsgStatus(DAS_ACQ_MAIN,TRUE);

    TransportManager *pTranArray[MAX_TASK_DIVID] = { 0 };

    RemoteService  * rmtService = new RemoteService();
    BaseInfo *baseInfo = new BaseInfo();
    ModuleInterface *pModules[DAS_TASK_MAX]={
        NULL,
        baseInfo,
        rmtService
    };

    int index;
    for (index = 0;index < MAX_TASK_DIVID;index++) {
        char center[20] = {0};
        sprintf(center,"CENTER%d",index+1);
        string strip = utils::GetConfigFileStringValue("Config.ini",center,"center","");
        if (strip == "") {
            if (index != 0)
                break;
            strip = utils::GetConfigFileStringValue("Config.ini","GATEWAY","center","");
            if (strip == "" )
            {
                LOG_ERR("no center set");
                return 0;
            }
        }

        /*
         * 初始化各功能模块
         */
        AcquisitionManager *acquireMgr =
                new AcquisitionManager(index);
        pModules[0] = acquireMgr;

        /*
         * 初始化传输模块
         */
        pTranArray[index] =
                new TransportManager(index);
        pTranArray[index]->SetupRemoteTask();
        pTranArray[index]->SetupLocalTask();

        for (S32 i = 0;i<DAS_TASK_MAX;i++){
            AddTask((DAS_TASK)i,index,pModules[i]);
            if (pModules[i])
                pTranArray[index]->RegisterModules(pModules[i]);
        }
    }
    SetCenterNum(index);

    /*
     * 初始化采集模块
     */
    dotask(0);

    //看门狗
    WatchDog   watchDog;
    /*
     * 等待信号
     */
    int ret = 0;
    if(!utils::WaitTerminationSignals(&sig_handler)){
        LOG_ERR("failed to catch signal");
        ret = 1;
    }

    for (int i = 0;i < MAX_TASK_DIVID;i++) {
        if (pTranArray[i])
            pTranArray[i]->ExitTask();
    }
    /*
     * 释放模块
     */
    dotask(1);

    for (int i = 0;i < MAX_TASK_DIVID;i++) {
        if (pTranArray[i])
            delete pTranArray[i];
    }

    dotask(2);

    LOG_ERR("exit %d",ret);
    return 0;
}

void dotask(int flag)
{
    LOG_INFO("%s task",flag == 0?"construct":flag == 1?"destroy":"delete");
    for (S32 j = 1;j < DAS_TASK_MAX; j++) {

        ModuleInterface *module = (ModuleInterface*)GetTask((DAS_TASK)j,0);
        if (!module)
            continue;
        if (flag == 0)
            module->Contruct(TRUE);
        else if (flag == 1)
            module->Contruct(FALSE);
        else if (flag == 2) {
            delete module;
        }
    }
    for (int i = 0;i < MAX_TASK_DIVID;i++) {
        ModuleInterface *module = (ModuleInterface*)GetTask((DAS_TASK)0,i);
        if (!module)
            continue;
        if (flag == 0)
            module->Contruct(TRUE);
        else if (flag == 1)
            module->Contruct(FALSE);
        else if (flag == 2) {
            delete module;
        }
    }
}

void sigint_catch(int sig) {
    LOG_INFO("sigint catch %d",sig);
//    exit(EXIT_FAILURE);
//    sig_handler(sig);
}

void sig_handler(int sig) {
  switch (sig) {
    case SIGINT:
      LOG_DEBUG("SIGINT signal has been caught");
//      sigint_catch(sig);
      exit(EXIT_FAILURE);
      break;
    case SIGTERM:
      LOG_DEBUG("SIGTERM signal has been caught");
      sigint_catch(sig);
      break;
    case SIGSEGV:
      LOG_DEBUG( "SIGSEGV signal has been caught");
      // exit need to prevent endless sending SIGSEGV
      // http://stackoverflow.com/questions/2663456/how-to-write-a-signal-handler-to-catch-sigsegv
      abort();
    default:
      LOG_DEBUG("Unexpected signal has been caught");
      sigint_catch(sig);
  }
}

void setVersion()
{
    char script[255];
    FILE *fp = NULL;
    char buffer[64] = {0};

    sprintf(script,"echo %s > %s/VERSION",DAS_VERSION,getenv(CONFIG_DIR_ENV));

    fp = popen(script,"r");

    LOG_INFO("shell:%s",script);

    while(fgets(buffer,sizeof(buffer),fp) != NULL) {
        LOG_INFO("%s",buffer);
    }
    pclose(fp);
}

